#include "ftp_client.h"

char recvbuf[BUF_SIZE];         // 用来存放接收的消息
// char sendbuf[BUF_SIZE];         // 用来存放发送的消息
char *filebuff;         // 用于存放服务器发送过来的文件
int g_file_size;        // 文件总大小
char filename[256];

bool connect_to_server(void)
{
    int sock_fd;
    
    // 创建套接字
    sock_fd = socket(AF_INET, SOCK_STREAM, 0);
    if(sock_fd < 0)
    {
        perror("socket()");
        return false;
    }

    // 填充服务端信息
    struct sockaddr_in servaddr;
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(PORT);
    // servaddr.sin_addr.s_addr = inet_addr("192.168.208.130");
    servaddr.sin_addr.s_addr = inet_addr("192.168.60.128");

    // 连接服务器
    int ret = connect(sock_fd, (struct sockaddr *)&servaddr, sizeof(servaddr));
    if(ret < 0)
    {
        perror("connect()");
        return false;
    }

    printf("----------------------------------------------------------------\n");
    printf("|                           请输入命令：                         |\n");
    printf("| 可选命令为：                                                   |\n");
    printf("| ls) 列出服务器所在目录的文件               cd) 进入到指定的目录 |\n");
    printf("| quit) 退出                                                     |\n");
    printf("----------------------------------------------------------------\n");
    
    char cmd[256] = {0};
    fgets(cmd, sizeof(cmd), stdin);
    cmd[strlen(cmd) - 1] = '\0';

    if(strcmp(cmd, "quit") == 0)
    {
        return true;
        close(sock_fd);
    }
    cmd_to_server(sock_fd, (char *)cmd);
    get_cmd_result(sock_fd);
    // 进行消息处理
    download_filename(sock_fd);
    while(processMsg(&sock_fd))
    {
        // sleep(2);
    }
    return true;


}

bool processMsg(int *clientfd)
{

    // printf("file_name = %s\n", file_name);
    // download_filename(*clientfd);

    memset(recvbuf, 0, sizeof(recv));
    int ret = recv(*clientfd, (char *)recvbuf, 1024, 0);
    MSG_HEAD *msg = (MSG_HEAD *)recvbuf;
    // printf("filename = %s       size = %d\n", msg->FILE_INFO.filename, msg->FILE_INFO.file_size);
    // printf()
    if(ret <= 0)
    {
        printf("客户端接收信息出错...\n");
        return false;
    }

    switch(msg->msg_ID)
    {
        case MSG_OPEN_FAILED:
            download_filename(*clientfd);
            break;
        case MSG_FILE_SIZE:
            // 准备内存空间，用于接收文件
            printf("MSG_FILE_SIZE\n");
            readyread(*clientfd, msg);
            break;
        case MSG_READY:
            printf("MSG_READY\n");
            write_file(*clientfd, msg);
            break;
        case MSG_SUCCESSED:
            // 收到成功响应，断开连接
            break_to_connet(*clientfd);
            return false;
            break;
    }
    return true;
}

void download_filename(int client)
{
    char file_name[1024] = {0};
    printf("请输入文件名：\n");
    fgets(file_name, 1023, stdin);
    file_name[strlen(file_name) - 1] = '\0';        // 将最后的换行符去掉

    MSG_HEAD file;
    memset(&file, 0, sizeof(file));
    file.msg_ID = MSG_FILE_NAME;        // 发送文件名
    strncpy(file.un.FILE_INFO.filename, file_name, 255);
    send(client, (char *)&file, sizeof(file), 0);

}

void readyread(int serv_fd, MSG_HEAD *pmsg)
{
    printf("filename = %s       size = %d\n", pmsg->un.FILE_INFO.filename, pmsg->un.FILE_INFO.file_size);
    // 准备内存
    strcpy(filename, pmsg->un.FILE_INFO.filename);
    g_file_size = pmsg->un.FILE_INFO.file_size;
    filebuff = (char *)calloc(g_file_size + 1, sizeof(char));
    if(filebuff == NULL)
    {
        printf("动态内存分配失败\n");
        return ;
    }
    // 给服务器发送一个MSG_SEND，代表客户端已经准备好接收文件了
    MSG_HEAD msg;
    memset(&msg, 0, sizeof(msg));
    msg.msg_ID = MSG_SEND;          // 表示服务器应该进行发送了
    int ret = send(serv_fd, (char *)&msg, sizeof(msg), 0);
    if(ret <= 0)
    {
        printf("发送 MSG_SEND 失败\n");
        return;
    }
}



void write_file(int serv_fd, MSG_HEAD *pmsg)
{
    if(filebuff == NULL)
    {
        return ;
    }

    // 在接收文件时，我们也需要分包接受
    int n_start = pmsg->un.Packet.pack_No;
    int size = pmsg->un.Packet.n_size;
    memcpy(filebuff + n_start, pmsg->un.Packet.file_buf, size);
    printf("packet:%d, %d\n", n_start + size, g_file_size);
    // 得到了完整的包
    if(size + n_start >= g_file_size)
    {
        FILE *fpw = fopen(filename, "wb");
        if(fpw == NULL)
        {
            printf("文件打开失败\n");
            return;
        }
        fwrite(filebuff, sizeof(char), g_file_size, fpw);

        free(filebuff);
        filebuff = NULL;

        MSG_HEAD msg;
        memset(&msg, 0, sizeof(msg));
        msg.msg_ID = MSG_SUCCESSED;
        send(serv_fd, (char *)&msg, sizeof(msg), 0);
        fclose(fpw);
    }

}

void break_to_connet(int serverfd)
{
    close(serverfd);
}

bool cmd_to_server(int serverfd, char *cmd)
{
    int ret = send(serverfd, cmd, strlen(cmd) + 1, 0);
    if(ret <= 0)
    {
        printf("客户端发送命令 ls 失败\n");
        return false;
    }
    return true;
}

bool get_cmd_result(int serverfd)
{
    while(1)
    {
        memset(recvbuf, 0, sizeof(recvbuf));
        int ret = recv(serverfd, (char *)recvbuf, BUF_SIZE, 0);
        if(ret <= 0)
        {
            return false;
        }
        if(strcmp(recvbuf,"finish") == 0)
            break;
        printf("%s\n",recvbuf);
    }

    return true;
}